home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / ISSUE19 / SYSTEM / SHELLLIN.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-02-09  |  7.2 KB  |  226 lines

  1. unit ShellLink;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
  7.  
  8. type
  9.   TShellLink = class(TComponent)
  10.   private
  11.     { Private declarations }
  12.     fTargetPath: String;
  13.     fLinkPath: String;
  14.     fDescription: String;
  15.     fArguments: String;
  16.     fWorkingDirectory: String;
  17.     fWindowState: TWindowState;
  18.     procedure SetLinkPath (const Val: String);
  19.     procedure Resolve (const FullLinkPath: String);
  20.   protected
  21.     { Protected declarations }
  22.   public
  23.     { Public declarations }
  24.     constructor Create (AOwner: TComponent); override;
  25.     destructor Destroy; override;
  26.     function Save: Boolean;
  27.    published
  28.     { Published declarations }
  29.     property WindowState: TWindowState read fWindowState write fWindowState default wsNormal;
  30.     property TargetPath: String read fTargetPath write fTargetPath;
  31.     property LinkPath: String read fLinkPath write SetLinkPath;
  32.     property Description: String read fDescription write fDescription;
  33.     property Arguments: String read fArguments write fArguments;
  34.     property WorkingDirectory: String read fWorkingDirectory write fWorkingDirectory;
  35.   end;
  36.  
  37. procedure Register;
  38.  
  39. implementation
  40.  
  41. uses Ole2, ShellAPI, ShellObj;
  42.  
  43. //----------------------------------------------------------------------
  44. //  Name:    GetIShellLink
  45. //  Purpose: Create an instance of the IShellLink interface
  46. //----------------------------------------------------------------------
  47.  
  48. function GetIShellLink: IShellLink;
  49. begin
  50.     if CoCreateInstance (CLSID_ShellLink, Nil, 1, IID_IShellLink, Result) < 0 then
  51.         Exception.Create ('Can''t get a shell link');
  52. end;
  53.  
  54. //----------------------------------------------------------------------
  55. //  Name:    GetIPersistFile
  56. //  Purpose: Given an IShellLink, get the IPersistFile interface.
  57. //----------------------------------------------------------------------
  58.  
  59. function GetIPersistFile (link: IShellLink): IPersistFile;
  60. begin
  61.     if link.QueryInterface (IID_IPersistFile, Result) < 0 then
  62.         Exception.Create ('Can''t get a persistent file');
  63. end;
  64.  
  65. //----------------------------------------------------------------------
  66. //  Name:    GetDeskTopFolder
  67. //  Purpose: Return location of Explorer's "live" desktop data
  68. //  Notes:   Yes, we could use SHGetDesktopFolder, but this is simpler.
  69. //----------------------------------------------------------------------
  70.  
  71. function GetDeskTopFolder: String;
  72. const
  73.     ShellFolders = 'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders';
  74. var
  75.     Key: hKey;
  76.     bytes: DWord;
  77.     szDest: array [0..Max_Path - 1] of Char;
  78. begin
  79.     Result := '';
  80.     if RegOpenKeyEx (HKey_Current_User, ShellFolders, 0, Key_Read, Key) = 0 then
  81.     try
  82.         bytes := sizeof (szDest);
  83.         if RegQueryValueEx (Key, 'Desktop', Nil, Nil, @szDest, @bytes) = 0 then
  84.         begin
  85.             Result := szDest;
  86.             Result := Result + '\';
  87.         end;
  88.     finally
  89.         RegCloseKey (Key);
  90.     end;
  91. end;
  92.  
  93. //----------------------------------------------------------------------
  94. //  Name:    FixUpLinkPath
  95. //  Purpose: Convert user-supplied link path into a fully qualified path.
  96. //----------------------------------------------------------------------
  97.  
  98. function FixUpLinkPath (const LinkPath: String): String;
  99. begin
  100.     Result := LinkPath;
  101.     if Pos ('.lnk', LowerCase (Result)) = 0 then Result := Result + '.lnk';
  102.     { Is this a fully-qualified pathname ? }
  103.     if ExtractFileDrive (Result) = '' then
  104.     begin
  105.         if Result[1] = '\' then Result := Copy (Result, 2, 255);
  106.         Result := GetDeskTopFolder + Result;
  107.     end;
  108. end;
  109.  
  110. { TShellLink }
  111.  
  112. constructor TShellLink.Create (AOwner: TComponent);
  113. begin
  114.     Inherited Create (AOwner);
  115.     CoInitialize (Nil);
  116.     WindowState := wsNormal;
  117. end;
  118.  
  119. destructor TShellLink.Destroy;
  120. begin
  121.     CoUninitialize;
  122.     Inherited Destroy;
  123. end;
  124.  
  125. procedure TShellLink.SetLinkPath (const Val: String);
  126. begin
  127.     if fLinkPath <> Val then
  128.     begin
  129.         fLinkPath := Val;
  130.         Resolve (FixUpLinkPath (fLinkPath));
  131.     end;
  132. end;
  133.  
  134. procedure TShellLink.Resolve (const FullLinkPath: String);
  135. var
  136.     swCmd: Integer;
  137.     link: IShellLink;
  138.     persist: IPersistFile;
  139.     FindData: TWin32FindData;
  140.     buff: array [0..511] of Char;
  141.     wLinkPath: array [0..Max_Path-1] of WideChar;
  142. begin
  143.     { Make sure the link file exists }
  144.     if FileExists (FullLinkPath) then
  145.     begin
  146.         { Pathname must be in WideChar format }
  147.         MultiByteToWideChar (cp_ACP, 0, PChar (FullLinkPath), -1, wLinkPath, Max_Path);
  148.         { Get a pointer to the wanted interface }
  149.         link := GetIShellLink;
  150.         try
  151.             // First, make sure we can get IPersistentFile
  152.             persist := GetIPersistFile (link);
  153.             try
  154.                 // Load the persistent object
  155.                 if persist.Load (wLinkPath, stgm_Read) >= 0 then
  156.                 begin
  157.                     link.GetPath (buff, sizeof (buff), FindData, slgp_ShortPath);
  158.                     TargetPath := buff;
  159.                     link.GetDescription (buff, sizeof (buff));
  160.                     Description := buff;
  161.                     link.GetArguments (buff, sizeof (buff));
  162.                     Arguments := buff;
  163.                     link.GetWorkingDirectory (buff, sizeof (buff));
  164.                     WorkingDirectory := buff;
  165.                     link.GetShowCmd (swCmd);
  166.                     case swCmd of
  167.                         sw_Minimize, sw_ShowMinimized:
  168.                             fWindowState := wsMinimized;
  169.                         sw_ShowMaximized:
  170.                             fWindowState := wsMaximized;
  171.                         else
  172.                             fWindowState := wsNormal;
  173.                     end;
  174.                 end;
  175.             finally
  176.                 persist.Release;
  177.             end;
  178.         finally
  179.             link.Release;
  180.         end;
  181.     end;
  182. end;
  183.  
  184. function TShellLink.Save: Boolean;
  185. var
  186.     swCmd: Integer;
  187.     link: IShellLink;
  188.     persist: IPersistFile;
  189.     wLinkPath: array [0..Max_Path-1] of WideChar;
  190. begin
  191.     Result := False;
  192.     { LinkPath must be in WideChar format }
  193.     MultiByteToWideChar (cp_ACP, 0, PChar (FixupLinkPath (LinkPath)), -1, wLinkPath, Max_Path);
  194.     { Get a pointer to the wanted interface }
  195.     link := GetIShellLink;
  196.     try
  197.         // First, make sure we can get IPersistentFile
  198.         persist := GetIPersistFile (link);
  199.         try
  200.             // Set target and description strings
  201.             link.SetPath (PChar (UpperCase (TargetPath)));
  202.             link.SetDescription (PChar (Description));
  203.             link.SetArguments (PChar (Arguments));
  204.             link.SetWorkingDirectory (PChar (WorkingDirectory));
  205.             case WindowState of
  206.                 wsMinimized:  link.SetShowCmd (sw_ShowMinimized);
  207.                 wsMaximized:  link.SetShowCmd (sw_ShowMaximized);
  208.                 wsNormal:     link.SetShowCmd (sw_ShowNormal);
  209.             end;
  210.             persist.Save (wLinkPath, True);
  211.             Result := True;
  212.         finally
  213.             persist.Release;
  214.         end;
  215.     finally
  216.         link.Release;
  217.     end;
  218. end;
  219.  
  220. procedure Register;
  221. begin
  222.   RegisterComponents ('Shell Tools', [TShellLink]);
  223. end;
  224.  
  225. end.
  226.